#include <iostream>
#include <type_traits>
#include <string>

// 使用if constexpr实现编译期条件
template<typename T>
auto get_value(T t) {
    if constexpr (std::is_integral_v<T>) {
        return t + 1;  // 整型加1
    } else if constexpr (std::is_floating_point_v<T>) {
        return t + 0.1;  // 浮点型加0.1
    } else if constexpr (std::is_same_v<T, std::string>) {
        return t + "!";  // 字符串添加感叹号
    } else {
        return t;  // 其他类型原样返回
    }
}

// 使用if constexpr处理可变参数模板
template<typename T>
void print_args(T t) {
    std::cout << t << '\n';
}

template<typename T, typename... Args>
void print_args(T t, Args... args) {
    std::cout << t << ", ";
    print_args(args...);  // 递归调用
}

template<typename... Args>
void print_all(Args... args) {
    if constexpr (sizeof...(args) == 0) {
        std::cout << "  无参数";
    } else {
        std::cout << "  参数值: ";
        print_args(args...);
    }
}

// 使用if constexpr简化SFINAE
template<typename T>
auto process(T value) {
    if constexpr (std::is_integral_v<T>) {
        // 整型特化
        return value * 2;
    } else if constexpr (std::is_floating_point_v<T>) {
        // 浮点型特化
        return value / 2.0;
    } else {
        // 非数值类型
        static_assert(
            std::is_integral_v<T> || std::is_floating_point_v<T>, 
            "仅支持数值类型"
        );
        return value; // 不会被编译，但需要有返回语句
    }
}

// 基于类型是否有特定方法的编译期条件选择
struct HasPrintMethod {
    void print() const { std::cout << "HasPrintMethod类打印方法\n"; }
};

struct NoPrintMethod {
    int value = 42;
};

// C++17兼容的方式检查方法是否存在
template<typename T, typename = void>
struct has_print_method : std::false_type {};

template<typename T>
struct has_print_method<T, std::void_t<decltype(std::declval<T>().print())>> : std::true_type {};

template<typename T>
void call_print_if_exists(const T& obj) {
    if constexpr (has_print_method<T>::value) {
        std::cout << "  对象有print方法: ";
        obj.print();
    } else {
        std::cout << "  对象没有print方法\n";
    }
}

void demonstrate_if_constexpr() {
    // 展示if constexpr根据类型处理不同分支
    std::cout << "  整型处理: " << get_value(42) << '\n';
    std::cout << "  浮点型处理: " << get_value(3.14) << '\n';
    std::cout << "  字符串处理: " << get_value(std::string("你好")) << '\n';
    
    // 展示参数个数检查
    print_all();
    std::cout << '\n';
    print_all(1, 2.5, "三", std::string("四"));
    std::cout << '\n';
    
    // 展示简化SFINAE
    std::cout << "  SFINAE简化:\n";
    std::cout << "  整型处理结果: " << process(10) << '\n';
    std::cout << "  浮点型处理结果: " << process(20.0) << '\n';
    // process("字符串");  // 会触发编译错误
    
    // 展示基于类型成员的条件选择
    std::cout << "  基于类型成员的条件:\n";
    HasPrintMethod has_print;
    NoPrintMethod no_print;
    
    call_print_if_exists(has_print);
    call_print_if_exists(no_print);
} 